//
// Created by juno on 2021/9/12.
//

#include <stdlib.h>
#include "room.h"
#include "common.h"

static unsigned int room_id = 0;
static struct room_t *rooms = NULL;

int room_create(struct room_t **list, struct room_info *info)
{
    struct room_t *room = calloc(1, sizeof(struct room_t));
    struct room_info *new = NULL;

    char *uuid = NULL;

    if (!room)
        return -1;

    if (gen_token(&uuid) < 0)
    {
        free(room);
        return -1;
    }

    new = calloc(1, sizeof(struct room_info));

    if (!new)
    {
        free(room);
        return -1;
    }

    new->name = strdup(info->name);
    new->owner = info->owner;
    new->uuid = uuid;
    room->info = new;
    room->member = info->owner;
    new->id = 0;

    room_id = 0;

    room_id++;

    *list = room;

    return 0;
}

int room_new(struct room_info *info, struct room_t **res)
{
    struct room_t *room = NULL;
    struct room_t *cur = rooms;
    struct room_t *next = NULL;
    struct room_info *new = NULL;

    char *uuid = NULL;

    if (cur == NULL)
    {
        if (room_create(&cur, info) < 0)
            return -ROOM_ERR_CODE_NOMEM;

        rooms = cur;
        *res = cur;
        goto out;

    } else {
        if (!strcmp(cur->info->name, info->name))
            return -ROOM_ERR_CODE_NOMEM;
        do {
            next = cur->next;

            if (next)
                if (!strcmp(next->info->name, info->name))
                    return -ROOM_ERR_CODE_EXIST;

            if (next)
                cur = next;

        }while(next);

        if (gen_token(&uuid) < 0)
            return -ROOM_ERR_CODE_UUID;

        room = calloc(1, sizeof(struct room_t));

        if (!room)
        {
            free(uuid);
            return -ROOM_ERR_CODE_NOMEM;
        }

        new = calloc(1, sizeof(struct room_info));

        if (!new)
        {
            free(uuid);
            free(room);
            return -ROOM_ERR_CODE_NOMEM;
        }

        new->name = strdup(info->name);
        new->owner = info->owner;
    }



    new->id = room_id;
    new->uuid = uuid;

    room_id++;

    room->info = new;

    cur->next = room;
    *res = room;

    out:
    return 0;
}

struct room_t *room_find_by_name(const char *name)
{
    struct room_t *cur = rooms;
    struct room_t *next = NULL;

    if (!rooms)
        return NULL;

    do {
        next = cur->next;

        if (!strcmp(cur->info->name, name))
            return cur;
        else
            cur = next;

    }while(cur);

    return NULL;
}

struct room_t *room_find_by_uuid(const char *uuid)
{
    struct room_t *cur = rooms;
    struct room_t *next = NULL;

    do {
        next = cur->next;
        if (!strcmp(cur->info->uuid, uuid))
            return cur;
        else
            cur = next;
    }while(cur);

    return NULL;
}

void rooms_iterator(void (*cb)(struct room_t *, void *), void *arg)
{
    struct room_t *cur = rooms;
    struct room_t *next = NULL;

    if (!rooms)
        return;

    do {
        next = cur->next;
        cb(cur, arg);
        cur = next;
    }while(cur);
}

void room_destroy(struct room_t *room)
{
    struct member_t *member = room->member;
    struct member_t *next = NULL;

    if (!member)
        goto out;

    do {
        next = member->next;
        free(member->base->name);
        free(member->base->uuid);
        free(member->base);
        free(member);
        member = next;
    }while(member);
out:
    free(room);
}
